// code from 'vscode'
export const LANGUAGE_DEFAULT = 'en';

let _isWindows = false;
let _isMacintosh = false;
let _isLinux = false;
let _isLinuxSnap = false;
let _isNative = false;
let _isWeb = false;
let _isElectron = false;
let _isIOS = false;
let _isMobile = false;
let _locale: string | undefined;
let _language: string = LANGUAGE_DEFAULT;
let _platformLocale: string = LANGUAGE_DEFAULT;
let _userAgent: string | undefined;

export interface IProcessEnvironment {
  [key: string]: string | undefined;
}

/**
 * This interface is intentionally not identical to node.js
 * process because it also works in sandboxed environments
 * where the process object is implemented differently. We
 * define the properties here that we need for `platform`
 * to work and nothing else.
 */
export interface INodeProcess {
  platform: string;
  arch: string;
  env: IProcessEnvironment;
  versions?: {
    node?: string;
    electron?: string;
    chrome?: string;
  };
  type?: string;
  cwd: () => string;
}

declare const process: INodeProcess;

const $globalThis: any = globalThis;

let nodeProcess: INodeProcess | undefined;

if (typeof process !== 'undefined' && typeof process?.versions?.node === 'string') {
  // Native environment (non-sandboxed)
  nodeProcess = process;
}

const isElectronProcess = typeof nodeProcess?.versions?.electron === 'string';
const isElectronRenderer = isElectronProcess && nodeProcess?.type === 'renderer';

interface INavigator {
  userAgent: string;
  maxTouchPoints?: number;
  language: string;
}
declare const navigator: INavigator;

// Native environment
if (typeof nodeProcess === 'object') {
  _isWindows = (nodeProcess.platform === 'win32');
  _isMacintosh = (nodeProcess.platform === 'darwin');
  _isLinux = (nodeProcess.platform === 'linux');
  _isLinuxSnap = _isLinux && Boolean(nodeProcess.env.SNAP) && Boolean(nodeProcess.env.SNAP_REVISION);
  _isElectron = isElectronProcess;
  _locale = LANGUAGE_DEFAULT;
  _language = LANGUAGE_DEFAULT;
  _isNative = true;
// Web environment
} else if (typeof navigator === 'object' && !isElectronRenderer) {
  _userAgent = navigator.userAgent;
  _isWindows = _userAgent.indexOf('Windows') >= 0;
  _isMacintosh = _userAgent.indexOf('Macintosh') >= 0;
  _isIOS = (_userAgent.indexOf('Macintosh') >= 0 || _userAgent.indexOf('iPad') >= 0 || _userAgent.indexOf('iPhone') >= 0) && Boolean(navigator.maxTouchPoints && navigator.maxTouchPoints > 0);
  _isLinux = _userAgent.indexOf('Linux') >= 0;
  _isMobile = _userAgent?.indexOf('Mobi') >= 0;
  _isWeb = true;
  _locale = LANGUAGE_DEFAULT;
  _language = _locale;
  _platformLocale = navigator.language;
// Unknown environment
} else {
  console.error('Unable to resolve platform.');
}

export const enum Platform {
  Web,
  Mac,
  Linux,
  Windows,
}
export type PlatformName = 'Web' | 'Windows' | 'Mac' | 'Linux';

export function PlatformToString(platform: Platform): PlatformName {
  switch (platform) {
    case Platform.Web: return 'Web';
    case Platform.Mac: return 'Mac';
    case Platform.Linux: return 'Linux';
    case Platform.Windows: return 'Windows';
  }
}

let _platform: Platform = Platform.Web;
if (_isMacintosh) {
  _platform = Platform.Mac;
} else if (_isWindows) {
  _platform = Platform.Windows;
} else if (_isLinux) {
  _platform = Platform.Linux;
}

export const isWindows = /*@__PURE__*/_isWindows;
export const isMacintosh = /*@__PURE__*/_isMacintosh;
export const isLinux = /*@__PURE__*/_isLinux;
export const isLinuxSnap = /*@__PURE__*/_isLinuxSnap;
export const isNative = /*@__PURE__*/_isNative;
export const isElectron = /*@__PURE__*/_isElectron;
export const isWeb = /*@__PURE__*/_isWeb;
export const isWebWorker = /*@__PURE__*/(_isWeb && typeof $globalThis.importScripts === 'function');
export const webWorkerOrigin = /*@__PURE__*/isWebWorker ? $globalThis.origin : undefined;
export const isIOS = /*@__PURE__*/_isIOS;
export const isMobile = /*@__PURE__*/_isMobile;
export const platform = /*@__PURE__*/_platform;
export const userAgent = /*@__PURE__*/_userAgent;

/**
 * The language used for the user interface. The format of
 * the string is all lower case (e.g. zh-tw for Traditional
 * Chinese)
 */
export const language = /*@__PURE__*/_language;

export namespace Language {

  export function value(): string {
    return language;
  }

  export function isDefaultVariant(): boolean {
    if (language.length === 2) {
      return language === 'en';
    } else if (language.length >= 3) {
      return language[0] === 'e' && language[1] === 'n' && language[2] === '-';
    } else {
      return false;
    }
  }

  export function isDefault(): boolean {
    return language === 'en';
  }
}

/**
 * The OS locale or the locale specified by --locale. The format of
 * the string is all lower case (e.g. zh-tw for Traditional
 * Chinese). The UI is not necessarily shown in the provided locale.
 */
export const locale = /*@__PURE__*/_locale;

/**
 * This will always be set to the OS/browser's locale regardless of
 * what was specified by --locale. The format of the string is all
 * lower case (e.g. zh-tw for Traditional Chinese). The UI is not
 * necessarily shown in the provided locale.
 */
export const platformLocale = /*@__PURE__*/_platformLocale;

export const enum OperatingSystem {
  Windows = 1,
  Macintosh = 2,
  Linux = 3,
}
export const OS = /*@__PURE__*/(_isMacintosh || _isIOS ? OperatingSystem.Macintosh : (_isWindows ? OperatingSystem.Windows : OperatingSystem.Linux));

export const isChrome = /*@__PURE__*/Boolean(userAgent && userAgent.indexOf('Chrome') >= 0);
export const isFirefox = /*@__PURE__*/Boolean(userAgent && userAgent.indexOf('Firefox') >= 0);
export const isSafari = /*@__PURE__*/Boolean(!isChrome && (userAgent && userAgent.indexOf('Safari') >= 0));
export const isEdge = /*@__PURE__*/Boolean(userAgent && userAgent.indexOf('Edg/') >= 0);
export const isAndroid = /*@__PURE__*/Boolean(userAgent && userAgent.indexOf('Android') >= 0);

export function isBigSurOrNewer(osVersion: string): boolean {
  return Number.parseFloat(osVersion) >= 20;
}
